package com.spring.demo3.factory;

import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.context.annotation.AnnotationScopeMetadataResolver;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.ScopeMetadataResolver;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.core.annotation.AliasFor;

import java.lang.annotation.*;

/**
 * ComponentScan描述
 *
 * ComponentScan工作的过程:
 *  1.Spring会扫描指定的包，且会递归下面子包，得到一批类的数组
 *  2.然后这些类会经过下面的各种过滤器，最后剩下的类会被注册到容器中
 *
 * 所以玩这个注解，主要关注2个问题:
 *  第一:需要扫描哪些包?通过value、basePackages、basePackageClasses这3个参数来控制
 *  第二:过滤器有哪些?通过useDefaultFilters、includeFilters、excludeFilters这3个参数来控制过滤器
 *
 *
 * @author vhans
 */
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(MyComponentScans.class)
public @interface MyComponentScan {

    // 指定需要扫描的包
    @AliasFor("basePackages")
    String[] value() default {};

    @AliasFor("value")
    String[] basePackages() default {};

    // 指定一些类,spring会扫描这些类所在的包以及其子包下的类
    Class<?>[] basePackageClasses() default {};

    // 自定义bean的生成器
    Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

    // 指定需要扫描资源的包
    Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;

    ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;

    // 指定要扫描包中的哪些资源,给出匹配模式
    String resourcePattern() default "**/*.class";

    // 对扫描的类是否启动默认过滤器
    // 规则是:凡是类上有@Repository、@Service、@Controller、@Component这几个注解中的任何一个的,这个类就会被作为bean注册到spring容器中
    boolean useDefaultFilters() default true;

    // 接收过滤器:用来匹配被扫描出来的哪些类会被作为组件注册到容器中
    MyComponentScan.MyFilter[] includeFilters() default {};

    // 排除过滤器:用来匹配被扫描出来的哪些类不被作为组件注册到容器中
    MyComponentScan.MyFilter[] excludeFilters() default {};

    // 是否延迟初始化被注册的bean
    boolean lazyInit() default false;

    @Retention(RetentionPolicy.RUNTIME)
    @Target({})
    public @interface MyFilter {
        // 过滤器的类型
        MyFilterType type() default MyFilterType.ANNOTATION;

        // ANNOTATION:指定一些注解
        // ASSIGNABLE_TYPE:指定类型
        // CUSTOM:指定用户自定义的过滤器,自定义过滤器要实现TypeFilter接口
        @AliasFor("classes")
        Class<?>[] value() default {};

        @AliasFor("value")
        Class<?>[] classes() default {};

        // 指定两种表达式的值
        String[] pattern() default {};
    }
}
